package com.dingreading.cloud.mall.util;

import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.*;
import com.dingreading.cloud.common.util.qyweixin.AccessTokenDto;
import com.dingreading.cloud.common.util.qyweixin.QyWeiXinUtil;
import com.dingreading.cloud.common.util.qyweixin.QyWeixinMsg;
import com.dingreading.cloud.mall.entity.*;
import com.dingreading.cloud.mall.service.*;
import com.dingreading.cloud.mall.util.redis.RedisService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 支付处理工具
 */
@RefreshScope
@Component
public class PayDealV3Util {

    public static PayDealV3Util util;

    @PostConstruct
    public void init() {
        util = this;
    }

    @Value("${serverUrl}")
    private String serverUrl;

    @Value("${qyweixin.corpid}")
    private String corpid;
    @Value("${qyweixin.secret}")
    private String secret;
    @Value("${qyweixin.agentid}")
    private String agentid;
    @Value("${qyweixin.mallchatid}")
    private String mallchatid;
    @Value("${qyweixin.selfUserid}")
    private String selfUserid;
    @Value("${qyweixin.thirdUserid}")
    private String thirdUserid;

//    @Resource
//    private OrderFormService orderFormService;
    @Resource
    private OrderFormServiceV5 orderFormService;
    @Resource
    private OrderFormLogService orderFormLogService;
//    @Resource
//    private ShopCartService shopCartService;
    @Resource
    private ShopCartV5Service shopCartService;
    @Resource
    private BalanceLogService balanceLogService;
    @Resource
    private CouponStaffService couponStaffService;
    @Resource
    private CouponStaffLogService couponStaffLogService;
    @Resource
    private CooperPayOrderService cooperPayOrderService;
    @Resource
    private StoresService storesService;
    @Resource
    private NjTicketOrderService ticketOrderService;
    @Resource
    private NjTicketUserService ticketUserService;
    @Resource
    private ReadstarPayOrderService readstarPayOrderService;
    @Resource
    private RedisService redisService;

    /**
     * 加盟门店-商品订单支付成功处理
     */
    public static R<Object> payOkGoodsOrder(
            String code, Integer payType, String tradeType, String tradeTypeName,
            String buyerId, String tradeNo, String payTime, String operatorUid, String operatorName,
            String remark, Integer payOnline
    ) throws Exception {
        OrderForm form = util.orderFormService.getByCode(null, code);
        if (form == null)
            return R.fail("获取订单失败");
        if (EnumType.BalanceProject.BUY_GOODS.getType() != form.getProjectType())
            return R.fail("不是商品订单");

        if (!form.getStatus().equals(EnumType.OrderForm.WAIT_PAY.getType())
                && !(form.getPayChannelCode().equals(EnumType.PayChannelCode.BANK.getType()) && form.getStatus().equals(EnumType.OrderForm.APPLY_BANKPAY.getType())))
            return R.fail(code + "，支付成功但订单状态错误！" + EnumType.OrderForm.getStatus(form.getStatus()));

        Stores stores = util.storesService.getByUid(form.getStoreUid());
        if (null == stores)
            return R.fail("门店信息获取失败");

        // 商品数据
        List<ShopCart> shopCartList = util.shopCartService.getByCode(form.getStaffUid(), code);
        if (CollectionUtils.isEmpty(shopCartList))
            return R.fail("订单的购物车记录获取失败");
        List<Integer> stockOutMethods = shopCartList.stream()
                .filter(shopCart -> shopCart.getStockOutMethod() != null)
                .map(ShopCart::getStockOutMethod).distinct().collect(Collectors.toList());

        Date time = DateUtil.getNowDatetime();
        // 更新订单支付信息
        boolean l = util.orderFormService.payOkGoodsOrder(form.getStaffUid(), code, payType, tradeType, buyerId, tradeNo, payOnline, payTime);
        if (!l)
            return R.fail("商品订单支付成功，更新信息失败" + code);

        // 更新购物车记录完成
        util.shopCartService.setOk(code, payTime);

        // 处理订单的代金券
        if (form.getCouponStaffId() != null) {
            String msg = dealCoupon(form, time);
            if (StringUtils.isNotBlank(msg))
                return R.fail(msg);
        }

        // 添加收支记录，实际支付金额大于0
        if (form.getPayPrice() >= 0) {
            newBalanceLog(form, EnumType.Payment.IN.getType(), payOnline, payType, tradeType, tradeTypeName, buyerId, tradeNo, payTime);
        }

        // 新建订单操作记录
        operatorUid = StringUtils.isBlank(operatorUid) ? form.getStaffUid() : operatorUid;
        operatorName = StringUtils.isBlank(operatorName) ? form.getStaffName() : operatorName;
        newOrderFormLog(form.getCode(), operatorUid, operatorName, "付款成功，待发货", remark);


        // 企业微信获取access_token
        String accessToken = getQiWeiAccessToken();
        /*if (!payType.equals(EnumType.PayType.BANK.getType())) {
            // 不是银行转账，删除银行转账截图
//            deleteBankImg(code);

            // 发送企业微信消息
            QyWeiXinUtil.sendToChat(accessToken, util.mallchatid, QyWeixinMsg.goodsPayMsg(util.serverUrl, form.getStoreName(), form.getCode(), payTime));
        } else {
            // 发送企业微信消息
            QyWeiXinUtil.sendToChat(accessToken, util.mallchatid, QyWeixinMsg.bankPayMsg(util.serverUrl, form.getStoreName(), form.getCode(), payTime));
        }*/
        if (AccountUtil.isJointOperation(stores.getOperationType(), form.getStaffUid())) {
            // 采购或联营店下单
            String msg = "";
            if (!payType.equals(EnumType.PayType.BANK.getType())) {
                // 发送群聊消息
                msg = QyWeixinMsg.jointOperationGoodsPayMsg(util.serverUrl, form.getStoreName(), form.getCode(), payTime);
                QyWeiXinUtil.sendToUser(accessToken, util.agentid, util.thirdUserid, msg);
            }
        } else {
            String msg = "";
            if (!payType.equals(EnumType.PayType.BANK.getType())) {
                // 发送群聊消息
                msg = QyWeixinMsg.goodsPayMsg(util.serverUrl, form.getStoreName(), form.getCode(), payTime);
            } else {
                // 发送群聊消息
                msg = QyWeixinMsg.bankPayMsg(util.serverUrl, form.getStoreName(), form.getCode(), payTime);
            }
            QyWeiXinUtil.sendToChat(accessToken, util.mallchatid, msg);
        }

        // 发送群聊消息通知-仓库
        sendDeliveryMsg(accessToken, form.getStoreName(), code, payTime, stockOutMethods);

        // 删除redis过期自动取消的商城订单号
        deleteMallCodeFromRedisExpire(code);

        return R.ok("商品订单支付处理成功");
    }

    /**
     * 自营门店-商品订单支付成功处理
     */
    public static String payOkSelfGoodsOrder(
            String headStaffUid, String headStaffName,
            OrderForm form, Integer payType, String tradeType, String tradeTypeName,
            String buyerId, String tradeNo, String remark
    ) throws Exception {
        if (form == null)
            return "获取订单失败";
        if (EnumType.BalanceProject.BUY_GOODS.getType() != form.getProjectType())
            return "不是商品订单";
        if (EnumType.OrderForm.WAIT_CONFIRM.getType() != form.getStatus())
            return "订单付款状态错误！付款状态：" + EnumType.OrderForm.getStatus(form.getStatus());

        String code = form.getCode();
        // 商品数据
        List<ShopCart> shopCartList = util.shopCartService.getByCode(form.getStaffUid(), code);
        if (CollectionUtils.isEmpty(shopCartList))
            return "订单的购物车记录获取失败";
        List<Integer> stockOutMethods = shopCartList.stream()
                .filter(shopCart -> shopCart.getStockOutMethod() != null)
                .map(ShopCart::getStockOutMethod).distinct().collect(Collectors.toList());

        Date time = DateUtil.getNowDatetime();
        String payTime = DateUtil.getNowDatetimeStr();
        // 更新订单支付信息
        boolean l = util.orderFormService.payOkGoodsOrder(form.getStaffUid(), code, payType, tradeType, buyerId, tradeNo, 1, payTime);
        if (!l)
            return "商品订单支付成功，更新信息失败！" + code;

        // 更新购物车记录完成
        util.shopCartService.setOk(code, payTime);

        // 处理订单的代金券
        if (form.getCouponStaffId() != null) {
            String msg = dealCoupon(form, time);
            if (StringUtils.isNotBlank(msg))
                return msg;
        }

        // 添加收支记录，实际支付金额大于0
        if (form.getPayPrice() >= 0) {
            newBalanceLog(form, EnumType.Payment.IN.getType(), 2, payType, tradeType, tradeTypeName, buyerId, tradeNo, payTime);
        }

        // 添加订单操作记录
        newOrderFormLog(form.getCode(), headStaffUid, headStaffName, "自营门店订单已确认，待发货", remark);

        // 企业微信获取access_token
        String accessToken = getQiWeiAccessToken();
        // 叮叮机器人消息通知-仓库
        sendDeliveryMsg(accessToken, form.getStoreName(), code, payTime, stockOutMethods);

        // 删除redis过期自动取消的商城订单号
        deleteMallCodeFromRedisExpire(code);

        return "";
    }

    /**
     * 商城赠品订单支付成功处理
     */
    public static String payOkGiftGoodsOrder(
            String staffUid, String staffName,
            OrderForm form, Integer payType, String tradeType, String payChannelCode, String remark
    ) throws Exception {
        String code = form.getCode();
        // 商品数据
        List<ShopCart> shopCartList = util.shopCartService.getByCode(form.getStaffUid(), code);
        if (CollectionUtils.isEmpty(shopCartList))
            return "订单的购物车记录获取失败";
        List<Integer> stockOutMethods = shopCartList.stream()
                .filter(shopCart -> shopCart.getStockOutMethod() != null)
                .map(ShopCart::getStockOutMethod).distinct().collect(Collectors.toList());

        String payTime = DateUtil.getNowDatetimeStr();
        // 更新订单支付信息
        boolean l = util.orderFormService.payOkGiftGoodsOrder(form.getStaffUid(), code, payType, tradeType, payChannelCode, payTime);
        if (!l)
            return "商品订单支付成功，更新信息失败！" + code;

        // 更新购物车记录完成
        util.shopCartService.setOk(code, payTime);

        // 添加订单操作记录
        newOrderFormLog(form.getCode(), staffUid, staffName, "赠品订单确认通过，待发货", remark);

        // 企业微信获取access_token
        String accessToken = getQiWeiAccessToken();
        // 叮叮机器人消息通知-仓库
        sendDeliveryMsg(accessToken, form.getStoreName(), code, payTime, stockOutMethods);

        // 删除redis过期自动取消的商城订单号
        deleteMallCodeFromRedisExpire(code);

        return "";
    }


    /**
     * 处理订单的代金券
     */
    private static String dealCoupon(OrderForm form, Date time) {
        CouponStaff couponStaff = util.couponStaffService.getStaffCoupon(form.getStoreUid(), form.getStaffUid(), form.getCouponStaffId());
        if (couponStaff == null)
            return "代金券获取失败或已失效";
        double usableMoney = NepUtil.nullToZero(couponStaff.getUsableMoney());
        double usedMoney = NepUtil.nullToZero(couponStaff.getUsedMoney());
        double useMoney = NepUtil.nullToZero(form.getCouponPrice());
        // 更新员工代金券的可用金额和已使用金额
        boolean c = util.couponStaffService.updateMoney(form.getStoreUid(), form.getStaffUid(), form.getCouponStaffId(),
                DoubleUtil.sum(usedMoney, useMoney), DoubleUtil.sub(usableMoney, useMoney));
        if (!c) {
            return "更新员工代金券金额失败";
        }
        // 添加员工代金券使用记录
        CouponStaffLog log = OrderFormV3Util.newCouponStaffLog(couponStaff, form.getCode(), useMoney, usableMoney);
        util.couponStaffLogService.saveOrUpdate(log);

        return "";
    }

    /**
     * 新建收支记录
     */
    private static void newBalanceLog(
            OrderForm form, Integer income, Integer payOnline, Integer payType, String tradeType, String tradeTypeName,
            String buyerId, String tradeNo, String payTime
    ) {
        String payChannelCode = form.getPayChannelCode();
        if (StringUtils.isNotBlank(payChannelCode)) {
            tradeTypeName = EnumType.PayChannelCode.getTypeName(payChannelCode);
        }
        BalanceLog balanceLog = OrderFormV3Util.newBalanceLog(form, income, payOnline, null, null,
                payType, tradeType, tradeTypeName, buyerId, tradeNo, payTime);
        util.balanceLogService.saveOrUpdate(balanceLog);
    }

    /**
     * 新建订单操作记录
     */
    private static void newOrderFormLog(String code, String operatorUid, String operatorName, String statusName, String remark) {
        // 添加订单操作记录
        OrderFormLog log = OrderFormV3Util.newStaffLog(code, operatorUid, operatorName, EnumType.OrderForm.WAIT_SEND.getType(), statusName, remark);
        util.orderFormLogService.saveOrUpdate(log);
    }

    /**
     * 发送群聊消息-仓库
     */
    private static void sendDeliveryMsg(String accessToken, String storeName, String code, String time, List<Integer> stockOutMethods) throws Exception {
        // 根据出库方式发送通知仓库人员
        if (stockOutMethods.contains(1) && stockOutMethods.contains(3)) {
            // 自营仓库+第三方仓库
            QyWeiXinUtil.sendToUser(accessToken, util.agentid, util.selfUserid, QyWeixinMsg.goodsWaitDeliveryMsg(util.serverUrl, storeName, code, time));

            QyWeiXinUtil.sendToUser(accessToken, util.agentid, util.thirdUserid, QyWeixinMsg.goodsThirdWaitDeliveryMsg(util.serverUrl, storeName, code, time));
        } else if (stockOutMethods.contains(1)) {
            // 自营仓库
            QyWeiXinUtil.sendToUser(accessToken, util.agentid, util.selfUserid, QyWeixinMsg.goodsWaitDeliveryMsg(util.serverUrl, storeName, code, time));
        } else if (stockOutMethods.contains(3)) {
            // 第三方仓库
            QyWeiXinUtil.sendToUser(accessToken, util.agentid, util.thirdUserid, QyWeixinMsg.goodsThirdWaitDeliveryMsg(util.serverUrl, storeName, code, time));
        }
        // 虚拟商品待发货通知
        if (stockOutMethods.contains(2)) {
            // 运营
            QyWeiXinUtil.sendToChat(accessToken, util.mallchatid, QyWeixinMsg.goodsOnlineWaitDeliveryMsg(util.serverUrl, storeName, code, time));
        }
    }


    /**
     * 合作费订单支付成功处理
     */
    public static R<Object> payOkCooperOrderPayOrder(
            String code, Integer payType, String tradeType, String tradeTypeName,
            String buyerId, String tradeNo, String payTime) {

        CooperPayOrder form = util.cooperPayOrderService.getByCode(code);
        if (null == form)
            return R.fail("订单获取失败");

        if (form.getStatus().equals(0)) {
            boolean l = util.cooperPayOrderService.payOk(code, payType, tradeType, buyerId, tradeNo, payTime);
            if (!l)
                return R.fail("合作订单订单支付成功，更新信息失败！" + code);
            BalanceLog balanceLog = OrderFormV3Util.newBalanceLog(form, EnumType.Payment.IN.getType(),
                    1, null, null, payType, tradeType,
                    EnumType.PayChannelCode.getTypeName(form.getPayChannelCode()), buyerId, tradeNo, payTime, form.getPayName());
            util.balanceLogService.saveOrUpdate(balanceLog);
        }

        return R.ok("合作费订单支付处理成功");
    }


    /**
     * 南京参会票支付成功处理
     */
    public static R<Object> payOkNjTicketOrder(
            String code, String tradeType,
            String buyerId, String tradeNo, String payTime, Date callBackTime
    ) {
        String year = String.valueOf(DateUtil.getYear());
        NjTicketOrder ticketOrder = util.ticketOrderService.getByCode(code, year);
        if (null == ticketOrder)
            return R.fail("ACEC参会票订单获取失败");

        if (ticketOrder.getPayStatus() != null && ticketOrder.getPayStatus().equals(0)) {
            boolean l = util.ticketOrderService.payOk(code, year, tradeType, buyerId, tradeNo, payTime, callBackTime);
            if (!l)
                return R.fail("南京参会票订单支付成功后更新信息失败！" + code);

            util.ticketUserService.upGradeTicketType(ticketOrder.getUserUid(), year);
        }

        return R.ok("南京参会票订单支付处理成功");
    }

    /**
     * 好读之星订单
     */
    public static R<Object> payOkReadstarPayOrder(
            String code, String tradeType, String buyerId, String tradeNo, String payTime, Date callBackTime
    ) {
        ReadstarPayOrder data = util.readstarPayOrderService.getByOrderCode(code);
        if (data == null)
            return R.fail("好读之星订单获取失败" + code);

        if (data.getPayStatus() != null && data.getPayStatus().equals(0)) {
            boolean l = util.readstarPayOrderService.payOk(code, tradeType, buyerId, tradeNo, payTime, callBackTime);
            if (!l)
                return R.fail("好读之星订单支付成功后更新信息失败" + code);
        }

        return R.ok("好读之星订单支付回调成功");
    }

    /**
     * 删除redis过期自动取消的商城订单号
     */
    private static void deleteMallCodeFromRedisExpire(String code) {
        OrderFormV3Util.deleteMallCodeFromRedisExpire(code);
    }

    /**
     * 企业微信获取access_token
     */
    private static String getQiWeiAccessToken() {
        String accessToken = (String) util.redisService.get(RedisParam.QYWEINXIN_ACCESS_TOKEN);
        if (StringUtils.isBlank(accessToken)) {
            AccessTokenDto dto = QyWeiXinUtil.getAccessToken(util.corpid, util.secret);
            if (dto != null) {
                accessToken = dto.getAccess_token();
                int expires_in = dto.getExpires_in();
                // redis缓存accessToken
                util.redisService.set(RedisParam.QYWEINXIN_ACCESS_TOKEN, accessToken, expires_in);
            }
        }
        return accessToken;
    }

}